﻿using BCCommon;
using BCCommon.Enums;
using BCData.Sim.Admin.Admin;
using BCData.Sim.Admin.TreePermission;
using BCData.Sim.Company.Company;
using BCData.Sim.Company.Department;
using BCDto.Common.TreeNode;
using BCDto.Sim.Admin.Admin;
using BCDto.Sim.Admin.AdminPermissionMappingPage;
using BCDto.Sim.Admin.TreePermission;
using BCEntity.Common.EntityNameConst;
using BCEntity.Sim.Admin.TreePermission;
using BCService.Sim.Admin.StaffOrganizationMappingRecord;
using BCService.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BCService.Sim.Admin.TreePermission
{
    public class TreePermissionRecordService : ITreePermissionRecordService
    {
        private readonly ITreePermissionRecordData treePermissionRecordData;
        private readonly ITreePermissionConfigData treePermissionConfigData;
        private readonly IAdminData adminData;
        private readonly IRedisService redisService;
        private readonly IDepartmentData departmentData;
        private readonly ICompanyData companyData;
        private readonly IStaffOrganizationMappingRecordService staffOrganizationMappingRecordService;
        private readonly string key = string.Format("{0}", EntityNameConst.TreePermissionRecordListEntity);

        public TreePermissionRecordService(ITreePermissionRecordData treePermissionRecordData,
            ITreePermissionConfigData treePermissionConfigData,
            IAdminData adminData,
            IRedisService redisService,
            IDepartmentData departmentData,
            ICompanyData companyData,
            IStaffOrganizationMappingRecordService staffOrganizationMappingRecordService)
        {
            this.treePermissionRecordData = treePermissionRecordData;
            this.treePermissionConfigData = treePermissionConfigData;
            this.adminData = adminData;
            this.redisService = redisService;
            this.departmentData = departmentData;
            this.companyData = companyData;
            this.staffOrganizationMappingRecordService = staffOrganizationMappingRecordService;
        }

        public void DeleteAdmin(long treePermissionConfigId, long staffOrganizationMappingRecordId)
        {
            this.treePermissionRecordData.DeleteStaffOrganizationMappingRecordId(treePermissionConfigId, staffOrganizationMappingRecordId).GetAwaiter().GetResult();
        }

        public void DeleteCompany(long treePermissionConfigId, int companyId)
        {
            this.treePermissionRecordData.DeleteCompany(treePermissionConfigId, companyId).GetAwaiter().GetResult();
        }

        public void DeleteDepartment(long treePermissionConfigId, int departmentId)
        {
            this.treePermissionRecordData.DeleteDepartment(treePermissionConfigId, departmentId).GetAwaiter().GetResult();
        }

        public IEnumerable<TreePermissionRecordViewDto> GetList(int? companyId, int? departmentId, long? adminId)
        {
            if (!companyId.HasValue && !departmentId.HasValue && !adminId.HasValue)
            {
                throw new ArgumentException("公司、部门、员工必须选择一个");
            }
            var result = this.treePermissionRecordData.GetList(companyId, departmentId, adminId).Result;

            return result.As<IEnumerable<TreePermissionRecordViewDto>>();
        }

        public (IEnumerable<TreePermissionConfigDto>, List<PageMenuDto>) GetTreePermissions(long? adminId)
        {
            string cacheKey = this.redisService.GetKey(key, adminId ?? 0);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                List<TreePermissionConfigEntity> treePermissionConfigList = new List<TreePermissionConfigEntity>();
                var data = this.treePermissionRecordData.GetListByAdminIdAsync(adminId).GetAwaiter().GetResult();
                foreach(var item in data)
                {
                    item.PagePathCode = item.PagePathCode.TrimStart('/');
                    treePermissionConfigList.Add(item);
                }
                return treePermissionConfigList;
            }, TimeSpan.FromMinutes(30));
            var configResult = result.As<IEnumerable<TreePermissionConfigDto>>();
            List<PageMenuDto> resultPageMenuData = new List<PageMenuDto>();
            resultPageMenuData.AddRange(configResult.Where(p => p.PermissionLevel == 0).OrderBy(p => p.PermissionOrder).As<List<PageMenuDto>>());
            GetChildrenPageMenu(configResult, resultPageMenuData);
            return (configResult, resultPageMenuData);
        }

        private void GetChildrenPageMenu(IEnumerable<TreePermissionConfigDto> data, List<PageMenuDto> result)
        {
            foreach (var item in result)
            {
                var childrenData = data.Where(p => p.PermissionType == PermissionType.Menu && p.PagePathCode.Contains(item.Path.TrimStart('/')) && p.PermissionLevel == item.Level + 1)
                    .OrderBy(p => p.PermissionOrder);
                var children = childrenData.As<List<PageMenuDto>>();
                if (children.Any())
                {
                    GetChildrenPageMenu(data, children);
                    item.Children = children;
                }
            }
        }

        public IEnumerable<TreeNodeDto<TreePermissionConfigDto>> GetPermissionTemplateTree(int? companyId, int? departmentId, long? staffOrganizationMappingRecordId)
        {
            if (!companyId.HasValue && !departmentId.HasValue && !staffOrganizationMappingRecordId.HasValue)
            {
                throw new ArgumentException("公司、部门、员工必须选择一个");
            }

            if (staffOrganizationMappingRecordId.HasValue)
            {
                return GetAdminPermisssionTree(staffOrganizationMappingRecordId.Value);
            }
            else if (departmentId.HasValue)
            {
                return GetDepartmentPermisssionTree(departmentId.Value);
            }
            else
            {
                return GetCompanyPermisssionTree(companyId.Value);
            }

        }

        private IEnumerable<TreeNodeDto<TreePermissionConfigDto>> GetCompanyPermisssionTree(int companyId)
        {
            var treePermissionConfigList = this.treePermissionConfigData.GetList(null, null, null, null).GetAwaiter().GetResult();
            var treePermissionRecordList = this.treePermissionRecordData.GetList(companyId, null, null).GetAwaiter().GetResult();

            List<TreeNodeDto<TreePermissionConfigDto>> list = new List<TreeNodeDto<TreePermissionConfigDto>>();
            var rootPermissions = treePermissionConfigList.Where(p => p.PermissionLevel == 0).OrderBy(p => p.PermissionOrder);

            foreach (var item in rootPermissions)
            {
                var root = new TreeNodeDto<TreePermissionConfigDto>();
                root.Title = item.PermissionName;
                root.Key = item.PermissionCode;
                root.SourceData = item.As<TreePermissionConfigDto>();
                root.IsLeaf = false;
                root.Checked = treePermissionRecordList.Any(p => p.TreePermissionConfigId.Equals(item.TreePermissionConfigId));
                root.Expanded = true;
                root.Children = GetTreeNodes(item.As<TreePermissionConfigDto>(), treePermissionConfigList.As<IEnumerable<TreePermissionConfigDto>>(), treePermissionRecordList.As<IEnumerable<TreePermissionRecordDto>>());
                list.Add(root);
            }

            return list.As<IEnumerable<TreeNodeDto<TreePermissionConfigDto>>>();
        }

        private IEnumerable<TreeNodeDto<TreePermissionConfigDto>> GetDepartmentPermisssionTree(int departmentId)
        {
            var departmentEntity = this.departmentData.GetById(departmentId).GetAwaiter().GetResult();

            List<TreePermissionConfigEntity> parentDepartmentList = new List<TreePermissionConfigEntity>();

            if (!departmentEntity.ParentDepartmentId.HasValue)
            {
                parentDepartmentList = this.treePermissionRecordData.GetList(departmentEntity.CompanyId, null, null).GetAwaiter().GetResult().As<List<TreePermissionConfigEntity>>();
            }
            else
            {
                parentDepartmentList = this.treePermissionRecordData.GetList(null, departmentEntity.ParentDepartmentId, null).GetAwaiter().GetResult().As<List<TreePermissionConfigEntity>>();
            }

            var treePermissionRecordList = this.treePermissionRecordData.GetList(null, departmentId, null).GetAwaiter().GetResult();

            List<TreeNodeDto<TreePermissionConfigDto>> list = new List<TreeNodeDto<TreePermissionConfigDto>>();
            var rootPermissions = parentDepartmentList.Where(p => p.PermissionLevel == 0).OrderBy(p => p.PermissionOrder);

            foreach (var item in rootPermissions)
            {
                var root = new TreeNodeDto<TreePermissionConfigDto>();
                root.Title = item.PermissionName;
                root.Key = item.PermissionCode;
                root.SourceData = item.As<TreePermissionConfigDto>();
                root.IsLeaf = false;
                root.Checked = treePermissionRecordList.Any(p => p.TreePermissionConfigId.Equals(item.TreePermissionConfigId));
                root.Expanded = true;
                root.Children = GetTreeNodes(item.As<TreePermissionConfigDto>(), parentDepartmentList.As<IEnumerable<TreePermissionConfigDto>>(), treePermissionRecordList.As<IEnumerable<TreePermissionRecordDto>>());
                list.Add(root);
            }

            return list.As<IEnumerable<TreeNodeDto<TreePermissionConfigDto>>>();
        }

        private IEnumerable<TreeNodeDto<TreePermissionConfigDto>> GetAdminPermisssionTree(long staffOrganizationMappingRecordId)
        {
            var adminEntity = this.staffOrganizationMappingRecordService.GetEntity(staffOrganizationMappingRecordId);

            List<TreePermissionConfigEntity> parentDepartmentList = this.treePermissionRecordData.GetList(null, adminEntity.DepartmentId, null).GetAwaiter().GetResult().As<List<TreePermissionConfigEntity>>();

            var treePermissionRecordList = this.treePermissionRecordData.GetList(null, null, staffOrganizationMappingRecordId).GetAwaiter().GetResult();

            List<TreeNodeDto<TreePermissionConfigDto>> list = new List<TreeNodeDto<TreePermissionConfigDto>>();
            var rootPermissions = parentDepartmentList.Where(p => p.PermissionLevel == 0).OrderBy(p => p.PermissionOrder);

            foreach (var item in rootPermissions)
            {
                var root = new TreeNodeDto<TreePermissionConfigDto>();
                root.Title = item.PermissionName;
                root.Key = item.PermissionCode;
                root.SourceData = item.As<TreePermissionConfigDto>();
                root.IsLeaf = false;
                root.Checked = treePermissionRecordList.Any(p => p.TreePermissionConfigId.Equals(item.TreePermissionConfigId));
                root.Expanded = true;
                root.Children = GetTreeNodes(item.As<TreePermissionConfigDto>(), parentDepartmentList.As<IEnumerable<TreePermissionConfigDto>>(), treePermissionRecordList.As<IEnumerable<TreePermissionRecordDto>>());
                list.Add(root);
            }

            return list.As<IEnumerable<TreeNodeDto<TreePermissionConfigDto>>>();
        }

        private List<TreeNodeDto<TreePermissionConfigDto>> GetTreeNodes(TreePermissionConfigDto parentConfig, IEnumerable<TreePermissionConfigDto> source, IEnumerable<TreePermissionRecordDto> records)
        {
            List<TreeNodeDto<TreePermissionConfigDto>> children = new List<TreeNodeDto<TreePermissionConfigDto>>();

            if (source.Any(p => p.ParentPermissionPathCode.Equals(parentConfig.PermissionPathCode)))
            {
                var list = source.Where(p => p.ParentPermissionPathCode.Equals(parentConfig.PermissionPathCode));
                foreach (var item in list)
                {
                    var child = new TreeNodeDto<TreePermissionConfigDto>();
                    child.Title = item.PermissionName;
                    child.Key = item.PermissionCode;
                    child.SourceData = item.As<TreePermissionConfigDto>();
                    child.Checked = records.Any(p => p.TreePermissionConfigId.Equals(item.TreePermissionConfigId));
                    child.Expanded = true;
                    child.Children = GetTreeNodes(item, source, records);
                    child.IsLeaf = child.Children.Count == 0;
                    children.Add(child);
                }
            }
            return children;
        }


        public TreePermissionRecordDto SettingAdmin(AdminDto admin, long treePermissionConfigId, long staffOrganizationMappingRecordId)
        {
            string key = string.Format("{0}:StaffOrganizationMappingRecordId={1}", EntityNameConst.TreePermissionRecordListEntity, staffOrganizationMappingRecordId);
            var staffOrganizationMappingRecordDto = this.staffOrganizationMappingRecordService.GetEntity(staffOrganizationMappingRecordId);
            if (staffOrganizationMappingRecordDto==null)
            {
                throw new ArgumentException("员工信息不存在");
            }
            var result = this.treePermissionConfigData.GetEntityAsync(treePermissionConfigId).Result;
            if (result == null)
            {
                throw new ArgumentException("此权限配置不存在");
            }

            var recordEntity = this.treePermissionRecordData.GetEntityByAdminIdAsync(staffOrganizationMappingRecordDto.StaffOrganizationMappingRecordId, treePermissionConfigId).Result;
            if (recordEntity == null)
            {
                TreePermissionRecordEntity entity = new TreePermissionRecordEntity
                {
                    TreePermissionConfigId = treePermissionConfigId,
                    StaffOrganizationMappingRecordId = staffOrganizationMappingRecordDto.StaffOrganizationMappingRecordId,
                    AdminId = staffOrganizationMappingRecordDto.AdminId,
                    CompanyId = staffOrganizationMappingRecordDto.CompanyId,
                    DepartmentId = staffOrganizationMappingRecordDto.DepartmentId,
                    CreateTime = DateTime.Now,
                    CreateAdminId = admin.AdminId,
                    CreateAdminName = admin.FullName,
                    EditAdminId = admin.AdminId,
                    EditAdminName = admin.FullName
                };
                recordEntity = this.treePermissionRecordData.InsertAsync(entity).GetAwaiter().GetResult();
                if (recordEntity != null)
                {
                    this.redisService.DeleteAsync(key);
                }
            }
            else
            {
                throw new ArgumentException("此员工已存在此权限!");
            }
            return recordEntity.As<TreePermissionRecordDto>();
        }

        public TreePermissionRecordDto SettingCompany(AdminDto admin, long treePermissionConfigId, int companyId)
        {
            var companyEntity = this.companyData.GetEntity(companyId).Result;
            if (companyEntity == null)
            {
                throw new ArgumentException("公司信息不存在");
            }
            var recordEntity = this.treePermissionRecordData.GetEntityByCompanyIdAsync(companyId, treePermissionConfigId).GetAwaiter().GetResult();
            if (recordEntity == null)
            {
                TreePermissionRecordEntity entity = new TreePermissionRecordEntity
                {
                    TreePermissionConfigId = treePermissionConfigId,
                    CompanyId = companyId,
                    CreateTime = DateTime.Now,
                    CreateAdminId = admin.AdminId,
                    CreateAdminName = admin.FullName,
                    EditAdminId = admin.AdminId,
                    EditAdminName = admin.FullName
                };
                recordEntity = this.treePermissionRecordData.InsertAsync(entity).GetAwaiter().GetResult();
                if (recordEntity != null)
                {
                    string key = string.Format("{0}:CompanyId={1}", EntityNameConst.TreePermissionRecordViewEntity, companyId);
                    this.redisService.DeleteAsync(key);
                }
            }
            else
            {
                throw new ArgumentException("此公司已存在此权限!");
            }
            return recordEntity.As<TreePermissionRecordDto>();
        }

        public TreePermissionRecordDto SettingDepartment(AdminDto admin, long treePermissionConfigId, int departmentId)
        {
            var departmentEntity = this.departmentData.GetById(departmentId).Result;
            if (departmentEntity == null)
            {
                throw new ArgumentException("部门信息不存在");
            }
            var recordEntity = this.treePermissionRecordData.GetEntityByDepartmentIdAsync(departmentId, treePermissionConfigId).GetAwaiter().GetResult();
            if (recordEntity == null)
            {
                TreePermissionRecordEntity entity = new TreePermissionRecordEntity
                {
                    TreePermissionConfigId = treePermissionConfigId,
                    CompanyId = departmentEntity.CompanyId,
                    DepartmentId = departmentId,
                    CreateTime = DateTime.Now,
                    CreateAdminId = admin.AdminId,
                    CreateAdminName = admin.FullName,
                    EditAdminId = admin.AdminId,
                    EditAdminName = admin.FullName
                };
                recordEntity = this.treePermissionRecordData.InsertAsync(entity).GetAwaiter().GetResult();
                if (recordEntity != null)
                {
                    string key = string.Format("{0}:DepartmentId={1}", EntityNameConst.TreePermissionRecordViewEntity, departmentId);
                    this.redisService.DeleteAsync(key);
                }
            }
            else
            {
                throw new ArgumentException("此部门已存在此权限!");
            }
            return recordEntity.As<TreePermissionRecordDto>();
        }
    }
}
